# -*- coding: utf-8 -*-
# Author   : ZhangQing
# Time     : 2025-08-05 23:12
# File     : main.py
# Project  : codebuddy_craft
# Desc     :

"""
应用启动入口 🚀

FastAPI应用的主入口文件
"""

import uvicorn
import asyncio
import time
import logging
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request, Response
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.gzip import GZipMiddleware

from backend.core.config import get_app_settings
from backend.database.connection import init_db, close_db_connections
from backend.utils.logger import setup_logging
from backend.utils.log_utils import log_api_request, log_api_response
from backend.middleware.logging_middleware import LoggingMiddleware  # ✅ 使用我们自定义的中间件
from backend.api import auth_routes, user_routes, project_routes, file_routes

# 加载配置
settings = get_app_settings()

# 设置日志系统 ✨
setup_logging(settings)

# 获取日志记录器
logger = logging.getLogger(__name__)


@asynccontextmanager
async def lifespan(app: FastAPI):
    """应用生命周期管理 🔄"""
    # 启动时执行
    logger.info("🚀 启动应用...")

    try:
        # 初始化数据库
        await init_db()
        logger.info("✅ 数据库初始化完成")

        # 记录启动完成
        logger.info(f"🎉 {settings.PROJECT_NAME} v{settings.PROJECT_VERSION} 启动完成")
        logger.info(f"📍 环境: {settings.ENVIRONMENT}")
        logger.info(f"🌐 服务地址: http://{settings.HOST}:{settings.PORT}")
        if settings.is_development:
            logger.info(f"📚 API文档: http://{settings.HOST}:{settings.PORT}/docs")

        yield

    except Exception as e:
        logger.error(f"❌ 应用启动失败: {e}", exc_info=True)
        raise
    finally:
        # 关闭时执行
        logger.info("🔒 关闭应用...")

        try:
            await close_db_connections()
            logger.info("✅ 数据库连接已关闭")
        except Exception as e:
            logger.error(f"❌ 关闭数据库连接失败: {e}")

        logger.info("👋 应用已关闭")


# 创建FastAPI应用
app = FastAPI(
    title=settings.PROJECT_NAME,
    version=settings.PROJECT_VERSION,
    debug=settings.DEBUG,
    docs_url="/docs" if settings.is_development else None,
    redoc_url="/redoc" if settings.is_development else None,
    lifespan=lifespan
)

# ========== 中间件配置 ==========

# 日志中间件 (使用我们自定义的中间件)
app.add_middleware(LoggingMiddleware)

# GZIP压缩中间件
app.add_middleware(GZipMiddleware, minimum_size=1000)

# CORS中间件
app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.CORS_ORIGINS,
    allow_credentials=True,
    allow_methods=settings.CORS_METHODS,
    allow_headers=settings.CORS_HEADERS,
)

# ========== 路由配置 ==========

# 注册API路由
app.include_router(auth_routes.router, prefix="/api/auth", tags=["🔐 认证"])
app.include_router(user_routes.router, prefix="/api/users", tags=["👤 用户"])
app.include_router(project_routes.router, prefix="/api/projects", tags=["📁 项目"])
app.include_router(file_routes.router, prefix="/api/files", tags=["📄 文件"])


# ========== 基础路由 ==========

@app.get("/")
async def root():
    """根路径 🏠"""
    logger.info("📍 访问根路径")

    return {
        "message": f"欢迎使用 {settings.APP_NAME} ✨",
        "version": settings.APP_VERSION,
        "environment": settings.ENVIRONMENT,
        "status": "running",
        "docs": "/docs" if settings.is_development else "已禁用",
        "timestamp": time.time()
    }


@app.get("/health")
async def health_check():
    """健康检查端点 🏥"""
    logger.debug("🏥 执行健康检查")

    try:
        from backend.database.connection import health_check

        # 数据库健康检查
        db_health = await health_check()

        # 系统健康状态
        system_status = "healthy" if db_health["status"] == "healthy" else "degraded"

        health_data = {
            "status": system_status,
            "version": settings.APP_VERSION,
            "environment": settings.ENVIRONMENT,
            "timestamp": time.time(),
            "uptime": "unknown",  # 可以添加启动时间跟踪
            "database": db_health,
            "services": {
                "api": "healthy",
                "database": db_health["status"]
            }
        }

        if system_status == "healthy":
            logger.debug("✅ 系统状态健康")
        else:
            logger.warning("⚠️ 系统状态降级")

        return health_data

    except Exception as e:
        logger.error(f"❌ 健康检查失败: {e}", exc_info=True)

        return {
            "status": "unhealthy",
            "version": settings.APP_VERSION,
            "environment": settings.ENVIRONMENT,
            "timestamp": time.time(),
            "error": str(e),
            "services": {
                "api": "healthy",
                "database": "unhealthy"
            }
        }


@app.get("/info")
async def app_info():
    """应用信息端点 ℹ️"""
    logger.debug("ℹ️ 获取应用信息")

    return {
        "name": settings.APP_NAME,
        "version": settings.APP_VERSION,
        "environment": settings.ENVIRONMENT,
        "debug": settings.DEBUG,
        "features": {
            "authentication": True,
            "file_upload": True,
            "ai_assistance": bool(settings.OPENAI_API_KEY),
            "email_verification": settings.ENABLE_EMAIL_VERIFICATION,
            "rate_limiting": settings.RATE_LIMIT_ENABLED,
            "websocket": settings.WS_ENABLED,
            "caching": settings.CACHE_ENABLED
        },
        "limits": {
            "max_file_size": settings.MAX_FILE_SIZE,
            "allowed_file_types": len(settings.ALLOWED_FILE_TYPES)
        }
    }


# ========== 异常处理器 ==========

@app.exception_handler(404)
async def not_found_handler(request: Request, exc):
    """404错误处理器 🔍"""
    logger.warning(
        f"🔍 页面未找到: {request.method} {request.url.path}",
        extra={
            "event_type": "not_found",
            "method": request.method,
            "path": request.url.path,
            "client_host": request.client.host if request.client else "unknown"
        }
    )

    return {
        "detail": "页面未找到",
        "status_code": 404,
        "path": request.url.path,
        "method": request.method
    }


@app.exception_handler(500)
async def internal_server_error_handler(request: Request, exc):
    """500错误处理器 💥"""
    logger.error(
        f"💥 服务器内部错误: {request.method} {request.url.path}",
        exc_info=True,
        extra={
            "event_type": "server_error",
            "method": request.method,
            "path": request.url.path,
            "client_host": request.client.host if request.client else "unknown"
        }
    )

    return {
        "detail": "服务器内部错误" if not settings.DEBUG else str(exc),
        "status_code": 500,
        "path": request.url.path,
        "method": request.method
    }


# ========== 开发工具路由 ==========

if settings.is_development:

    @app.get("/dev/logs")
    async def get_recent_logs():
        """获取最近的日志 (仅开发环境) 🔧"""
        try:
            import os
            from pathlib import Path

            if not settings.LOG_FILE or not os.path.exists(settings.LOG_FILE):
                return {"message": "日志文件不存在"}

            # 读取最后100行日志
            with open(settings.LOG_FILE, 'r', encoding='utf-8') as f:
                lines = f.readlines()
                recent_logs = lines[-100:] if len(lines) > 100 else lines

            return {
                "total_lines": len(lines),
                "showing": len(recent_logs),
                "logs": [line.strip() for line in recent_logs]
            }

        except Exception as e:
            logger.error(f"❌ 获取日志失败: {e}")
            return {"error": str(e)}


    @app.post("/dev/reset-db")
    async def reset_database_dev():
        """重置数据库 (仅开发环境) ⚠️"""
        try:
            from backend.database.connection import reset_database

            logger.warning("⚠️ 开发环境数据库重置请求")
            await reset_database()
            logger.info("✅ 数据库重置完成")

            return {"message": "数据库重置成功"}

        except Exception as e:
            logger.error(f"❌ 数据库重置失败: {e}")
            return {"error": str(e)}


# ========== 启动函数 ==========

def create_app() -> FastAPI:
    """创建FastAPI应用实例 🏭"""
    return app


if __name__ == "__main__":
    logger.info("🚀 通过命令行启动应用")

    # 运行服务器
    uvicorn.run(
        "main:app",
        host=settings.HOST,
        port=settings.PORT,
        reload=settings.RELOAD and settings.is_development,
        workers=settings.WORKERS if settings.is_production else 1,
        log_level=settings.LOG_LEVEL.lower(),
        access_log=True,
        log_config=None,  # 使用我们自定义的日志配置
    )